﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using GC_VKMD.MusicDownloader.Helpers.Parameters;
using GC_VKMD.MusicDownloaderClient.Helpers;
using GC_VKMD.MusicDownloaderClient.ViewModels.Parameters;

namespace GC_VKMD.MusicDownloaderClient.ViewModels
{
	public class MusicDownloaderViewModel : INotifyPropertyChanged
	{
		#region Variables

		private readonly MusicDownloaderViewModelParameters _parameters;

		private bool _isWebBrowserVisible;
		private bool _isProgressBarVisible;
		private bool _isReportVisible;
		private double _progressBarMaximum;
		private double _progressBarCurrent;
		private double _progressBarValue;
		private string _progressBarStatusMessage;
		private ObservableCollection<MusicDownloaderReportItem> _report;

		private readonly AutoResetEvent _resetEvent;

		#endregion

		#region Properties

		public bool IsWebBrowserVisible
		{
			get { return _isWebBrowserVisible; }
			set
			{
				_isWebBrowserVisible = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("IsWebBrowserVisible"));
			}
		}

		public bool IsProgressBarVisible
		{
			get { return _isProgressBarVisible; }
			set
			{
				_isProgressBarVisible = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("IsProgressBarVisible"));
			}
		}

		public bool IsReportVisible
		{
			get { return _isReportVisible; }
			set
			{
				_isReportVisible = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("IsReportVisible"));
			}
		}

		public double ProgressBarValue
		{
			get { return _progressBarValue; }
			set
			{
				_progressBarValue = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("ProgressBarValue"));
			}
		}

		public string ProgressBarStatusMessage
		{
			get { return _progressBarStatusMessage; }
			set
			{
				_progressBarStatusMessage = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("ProgressBarStatusMessage"));
			}
		}

		public ObservableCollection<MusicDownloaderReportItem> Report
		{
			get { return _report; }
			set
			{
				_report = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("Report"));
			}
		}

		#endregion

		#region Constructors

		public MusicDownloaderViewModel(MusicDownloaderViewModelParameters parameters)
		{
			if (parameters == null)
				throw new ArgumentNullException(string.Format("Parameters"));
			_parameters = parameters;

			if (parameters.WindowManager == null)
				throw new ArgumentNullException(string.Format("windowManager"));

			if (parameters.ApplicationConfiguration == null)
				throw new ArgumentNullException(string.Format("ApplicationConfiguration"));

			if (parameters.VkMusicDownloader == null)
				throw new ArgumentNullException(string.Format("VkMusicDownloader"));

			_resetEvent = new AutoResetEvent(false);

			FillViewModel();
		}

		#endregion

		#region Internal Implementation

		private void FillViewModel()
		{
			IsWebBrowserVisible = true;
			IsProgressBarVisible = false;
			IsReportVisible = false;

			ProgressBarValue = 0;

			var worker = new BackgroundWorker();
			worker.DoWork += Autorization_DoWork;
			worker.RunWorkerCompleted += Autorization_DoWorkComplete;
			worker.RunWorkerAsync();
		}

		private void Autorization_DoWork(object sender, DoWorkEventArgs e)
		{
			while (true)
			{
				try
				{
					_parameters.ApplicationConfiguration.ReopenConfigFile();

					if (string.IsNullOrWhiteSpace(_parameters.ApplicationConfiguration.Token) ||
					    string.IsNullOrWhiteSpace(_parameters.ApplicationConfiguration.UserId)) continue;

					IsWebBrowserVisible = false;
					IsProgressBarVisible = true;

					StartDownloadMusicProcess();

					break;
				}
				finally
				{
					SafeOperationsManager.SafeExecute(() =>
					{
						if (_resetEvent != null)
							_resetEvent.WaitOne(1000);
					});
				}
			}
		}

		private void Autorization_DoWorkComplete(object sender, RunWorkerCompletedEventArgs e)
		{
			if (e.Error == null) return;
			ApplicationLogger.Logger.LoggingExceptionMessage(e.Error);
		}

		private void StartDownloadMusicProcess()
		{
			var report = _parameters.VkMusicDownloader.DownloadMusic(new VKMusicDownloaderParameters
			{
				FolderPath = _parameters.ApplicationConfiguration.Folder,
				Token = _parameters.ApplicationConfiguration.Token,
				UserId = _parameters.ApplicationConfiguration.UserId,
				AudioTracksCount = _parameters.ApplicationConfiguration.AudioTracksCount,
				SuccessfulDownloadFileAction = s =>
				{
					UpdateProgressBarValue();
					ProgressBarStatusMessage = s;
				},
				ErrorDownloadFileAction = s =>
				{
					UpdateProgressBarValue();
					ProgressBarStatusMessage = s;
				},
				FilesCountAction = i =>
				{
					_progressBarMaximum = i;
				}
			});

			if (report != null && report.Messages != null)
				Report =
					new ObservableCollection<MusicDownloaderReportItem>(report.Messages.Select(m => new MusicDownloaderReportItem(m)));

			IsProgressBarVisible = false;
			IsReportVisible = true;
		}

		private void UpdateProgressBarValue()
		{
			_progressBarCurrent++;
			ProgressBarValue = Math.Abs(_progressBarCurrent) > 0 && Math.Abs(_progressBarMaximum) > 0
				? _progressBarCurrent / _progressBarMaximum * 100
				: 100;
		}

		#endregion

		#region INotifyPropertyChanged Members

		public event PropertyChangedEventHandler PropertyChanged;

		protected virtual void OnPropertyChanged(string propertyName)
		{
			var handler = PropertyChanged;
			if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
		}

		#endregion
	}
}
